home *** CD-ROM | disk | FTP | other *** search
/ SuperHack / SuperHack CD.bin / Hack / UTILS / WPCRACKA.ZIP / WPCRACK.C next >
C/C++ Source or Header  |  1996-03-03  |  12KB  |  477 lines

  1.  
  2. /*----------------------------------------------------------------------
  3. **  WPCRACK - Copyright (c) 1990, 91 Ron Dippold 10/11/91
  4. **  rdippold@qualcomm.com
  5. **
  6. **  Attempt to crack a Word Perfect 5.x file through some massive
  7. **  security holes.
  8. **
  9. **  This source code is hereby released for public use.  All I ask is
  10. **  that if you make some cool new additions or enhancements that you
  11. **  mail me the update.  And if you use the program or source code,
  12. **  give me a little credit.
  13. **
  14. **  There's at least one major enhancement that could be made to this
  15. **  that I can think of at the moment - frequency analysis on the
  16. **  actual document text.  Once you know the format, it's pretty easy.
  17. **
  18. **  I'm not claiming this is the best code you've ever seen, it's just
  19. **  a fast hack, but it works.  I tried to be generic as possible so
  20. **  that it will compile on almost any platform.  It was written under
  21. **  Borland C.
  22. **----------------------------------------------------------------------*/
  23.  
  24. #include <stdio.h>
  25.  
  26. #define MAX 18        /* Max number of chars to look for */
  27. #define N 5           /* Max number of repeats */
  28.  
  29. FILE *f;              /* File name */
  30.  
  31. typedef unsigned char byte;
  32. typedef unsigned int  word;
  33.  
  34. byte buf1[48];
  35. byte *buf;
  36.  
  37. word csum1, csum, missing, mi;
  38.  
  39. /* bytes in the plaintext we think we know - 0x00 means we don't know */
  40. byte known[32] = {
  41.     0xfb, 0xff, 0x05, 0x00, 0x32, 0x00, 0x99, 0x99,
  42.     0x00, 0x00, 0x99, 0x99, 0x99, 0x00, 0x00, 0x00,
  43.     0x42, 0x00, 0x00, 0x00, 0x99, 0x00, 0x99, 0x00,
  44.     0x00, 0x00, 0x99, 0x00, 0x00, 0x00, 0x99, 0x99 };
  45.  
  46. byte source[MAX][N][MAX];   /* source table from known bytes */
  47. char pass[MAX][N][MAX];     /* possible passwords */
  48. char tots[MAX][MAX];        /* totals and matches for each password position */
  49. char mats[MAX][MAX];
  50. int  conf[MAX];             /* confidence for each length */
  51.  
  52. char chr[N];                /* character and count for each char */
  53. byte cnt[N];
  54.  
  55. char fmt[N][MAX];           /* characters for output */
  56. byte cnts[N][MAX];
  57.  
  58. int order[MAX];             /* order by confidence */
  59. int thresh=80;              /* threshold of confidence */
  60. int num=0;                  /* number of lengths that beat threshold */
  61.  
  62. byte pp;
  63. char c;
  64.  
  65. byte idx[MAX];              /* current guess */
  66. char cur[MAX];
  67.  
  68. int i, j, k, l, t, len, tot, match, deep;
  69. int do_dec=0, do_table=0;
  70.  
  71. void docs() {
  72.     printf( " To attempt to crack a Word Perfect 5.x file, the syntax is:\n\n" );
  73.     printf( "   WPCRACK (-d) (-t) <filename> ( <threshold> )\n\n" );
  74.     printf( " <filename> is the Word Perfect file to crack.\n" );
  75.     printf( " <threshold> is the percentage confidence threshold over which\n" );
  76.   printf( "    a length is considered to be a possibility.\n" );
  77.     printf( "    From 0 (all) to 100 (exact match), default 80.\n" );
  78.     printf( " The -d switch will force WPCRACK to the decimal values of\n");
  79.     printf( "    each character of an answer as well.  Not pretty.\n");
  80.     printf( " The -t switch will force WPCRACK to print all answers in table\n");
  81.     printf( "    form with all possibilities, ignoring checksums.\n");
  82.     printf( "\n\n To decrypt the file with the password, run WPUNCRYP on it.\n");
  83.     exit( 1 );
  84. }
  85.  
  86. void main( int argc, char **argv )
  87. {
  88.     printf( "\nWPCRACK 1.0 - Copyright (c) 1990,91 Ron Dippold\n\n" );
  89.  
  90.     if( argc < 2 || argc > 5 ) {
  91.         docs();
  92.     }
  93.  
  94.     i=1;
  95.  
  96.     while( i<argc && argv[i][0] == '-' ) {
  97.         if( argv[i][1] == 'd' ) {
  98.             do_dec = 1;
  99.         } else {
  100.             if( argv[i][1] == 't' ) {
  101.                 do_table = 1;
  102.             } else {
  103.                 docs();
  104.             }
  105.         }
  106.         i++;
  107.     }
  108.  
  109.     if( i>= argc ) {
  110.         docs();
  111.     }
  112.  
  113.     if( i == argc-2  ) {
  114.         sscanf( argv[i+1], "%d", &thresh );
  115.         if( thresh<0 || thresh>100 ) {
  116.             docs();
  117.         }
  118.     }
  119.  
  120.     if( !( f = fopen( argv[i], "rb" ))) {
  121.         printf( "  Could not open file %s\n", argv[i] );
  122.         exit( 2 );
  123.     }
  124.  
  125.     fseek( f, 0L, SEEK_SET );
  126.     if( fread( buf1, 1, 4, f ) != 4) {
  127.         fclose( f );
  128.         printf( "  Couldn't read 4 bytes from file %s!\n", argv[i] );
  129.         exit( 3 );
  130.     }
  131.  
  132.     if( buf1[0]!=0xff || buf1[1]!=0x57 || buf1[2]!=0x50 || buf1[3]!=0x43 ) {
  133.         printf( "%x, %x, %x, %x\n", buf1[0], buf1[1], buf1[2], buf1[3] );
  134.         fclose( f );
  135.         printf( "  The identification bytes in this file are not those of a\n" );
  136.         printf( "  Word Perfect 5.x file.\n" );
  137.         exit( 4 );
  138.     }
  139.  
  140.     if( fread( &buf1[4], 1, 44, f ) != 44 ) {
  141.         fclose( f );
  142.         printf( "  Couldn't read the first 48 bytes of the file - garbaged!\n" );
  143.         exit( 5 );
  144.     }
  145.     fclose( f );
  146.  
  147.     if( buf1[12]==0 && buf1[13]==0 ) {
  148.         printf( "  The file claims it is not encrypted.\n" );
  149.         printf( "  We'll continue anyway, but take note!\n\n%c",7 );
  150.     }
  151.  
  152.     csum1 = (buf1[12]<<8) + buf1[13];
  153.  
  154.     buf = &buf1[16];
  155.  
  156. /*  printf( "Building known text table.\n" ); */
  157.     for( i=1; i<MAX; i++ ) {
  158.         for( j=0; j<N; j++ ) {
  159.             for( k=0; k<i; k++ ) {
  160.                 pp = j*i+k;
  161.                 while ( pp<= 31 ) {
  162.                     if( known[pp] == 0x99 ) {
  163.                         pp+=i; continue;
  164.                     }
  165.                     tot = 0;
  166.                     if( j>0 ) for( l=j-1; l>=0; l-- ) {
  167.                         if( pp == source[i][l][k] ) {
  168.                             tot++;
  169.                         }
  170.                     }
  171.                     if( tot ) {
  172.                         pp+=i;
  173.                     } else {
  174.                         break;
  175.                     }
  176.                 }
  177.                 if ( pp>31 ) pp = 0xFF;
  178.                 source[i][j][k] = pp;
  179.             }
  180.         }
  181.     }
  182.  
  183. /*  printf("Trying password lengths from 1 to %d\n", MAX-1 ); */
  184.     for( len=1; len<MAX; len++ ) {
  185. /* printf( "Len %2d:\n", len ); */
  186.     for( j=0; j<N; j++ ) {
  187.             for( k=0; k<len; k++ ) {
  188.                 l = source[len][j][k];
  189.                 if( l != 0xFF && known[l] != 0x99 ) {
  190.                     pp = ( len+l+1 ) ^ known[l] ^ buf[l];
  191.                     if( pp>127 || (pp>='a' && pp<='z')) pp = 0;
  192. /* putchar( pp ); */
  193.                 } else {
  194.                     pp = 0;
  195. /* putchar( '_'); */
  196.                 }
  197.                 pass[len][j][k] = pp;
  198.             }
  199. /* printf( "\n" ); */
  200.         }
  201.  
  202.     /* move all good choices to the top */
  203.         for( k=0; k<len; k++ ) {
  204.             for( j=0; j<N-1; j++ ) {
  205.                 if( pass[len][j][k] == 0 ) {
  206.                     for( l=j; l<N-1; l++ ) {
  207.                         pass[len][l][k] = pass[len][l+1][k];
  208.                     }
  209.                     pass[len][N-1][k] = 0;
  210.                 }
  211.             }
  212.         }
  213.  
  214.         tot=match=0;
  215.         for( k=0; k<len; k++ ) {
  216.             tots[len][k] = mats[len][k] = 0;
  217.             for( j=1; j<N; j++ ) {
  218.                 if( pass[len][j][k] != 0 ) {
  219.                     tots[len][k]+=j;
  220.                     for( i=0; i<j; i++ ) {
  221.                         if( pass[len][j][k] == pass[len][i][k] ) {
  222.                             mats[len][k]++;
  223.                         }
  224.                     }
  225.                 }
  226.             }
  227.             tot+=tots[len][k];
  228.             match+=mats[len][k];
  229.         }
  230.  
  231.         if( tot ) {
  232.             conf[len] = match*100 / tot ;
  233.         } else {
  234.             conf[len]=0;
  235.         }
  236.     }
  237.  
  238. /*  printf( "Sorting results\n\n" ); */
  239.     for( i=0; i<MAX; i++ ) {
  240.         order[i] = i;
  241.     }
  242.  
  243.   /* so it's a bubble sort.  It's small.  Deal with it. */
  244.     for( i=MAX-1; i>0; i-- ) {
  245.         for( j=1; j<i; j++ ) {
  246.             if( conf[order[j]] < conf[order[j+1]] ) {
  247.                 k = order[j]; order[j] = order[j+1]; order[j+1] = k;
  248.             }
  249.         }
  250.     }
  251.  
  252.     for( num=MAX-1; num>0; num-- ) {
  253.         if( conf[order[num]]>=thresh ) {
  254.             break;
  255.         }
  256.     }
  257.  
  258.     printf( "%d length%c meet%c the %d%% initial confidence threshold.\n",
  259.         num, num==1 ? ' ':'s', num==1 ? 's':' ', thresh );
  260.  
  261.     if( num == 0 ) {
  262.         printf( "  Try lowering the threshold.\n");
  263.         printf( "  Or maybe you need a new version of this to match a Word Perfect change.\n" );
  264.         exit( 2 );
  265.     }
  266.  
  267.     for( l=1; l<=num; l++ ) {
  268.         len = order[l];
  269.         printf( "\nPassword length of %d with %d%% confidence level:\n\n",
  270.             len, conf[len] );
  271.  
  272.         deep=0;
  273.     /* for each character */
  274.         for( k=0; k<len; k++ ) {
  275.             for( j=0; j<N; j++ ) {
  276.                 fmt[j][k]=' ';
  277.                 cnts[j][k]=0;
  278.             }
  279.  
  280.       /* run a character vote */
  281.             for( j=0; j<N; j++ ) {
  282.                 chr[j]=cnt[j]=0;
  283.             }
  284.             for( j=0; j<N; j++ ) {
  285.                 if( pass[len][j][k] != 0 ) for(i=0; i<N; i++ ) {
  286.                     if( !chr[i] ) {
  287.                         chr[i] = pass[len][j][k];
  288.                     }
  289.                     if( pass[len][j][k] == chr[i] ) {
  290.                         cnt[i]++;
  291.                         break;
  292.                     }
  293.                 }
  294.             }
  295.       for( i=N-1; i>0; i-- ) {      /* sort to find most popular */
  296.                 for( j=0; j<i; j++ ) {
  297.                     if( cnt[j] < cnt[j+1] ) {
  298.                         t = cnt[j]; cnt[j] = cnt[j+1]; cnt[j+1] = t;
  299.                         t = chr[j]; chr[j] = chr[j+1]; chr[j+1] = t;
  300.                     }
  301.                 }
  302.             }
  303.  
  304.       if( cnt[0] == 0 ) {           /* no letters */
  305.                 fmt[0][k]='_';
  306.                 cnts[0][k]=0;
  307.             } else {
  308.                 for( j=0; j<N; j++ ) {
  309.                     if( cnt[j] ) {
  310.                         cnts[j][k]=cnt[j];
  311.                         fmt[j][k]=chr[j];
  312.                         if( deep<j) deep = j;
  313.                     }
  314.                 }
  315.             }
  316.         }
  317.  
  318.     /* Find any missing letters */
  319.         missing = 0; mi=-1;
  320.         for( k=0; k<len; k++ ) {
  321.             if( !cnts[0][k] ) {
  322.                 missing++;
  323.                 mi = k;
  324.             }
  325.         }
  326.  
  327.         if( missing > 1 || do_table ) {
  328.             if( missing > 1) {
  329.                 printf("  More than one letter is missing - showing all possibilities.\n");
  330.             } else {
  331.                 printf("  Displaying table form as requested\n");
  332.             }
  333.  
  334.       /* show in table form */
  335.             for( j=0; j<=deep; j++ ) {
  336.                 printf( "   # of matches: " );
  337.                 for( k=0; k<len; k++ ) {
  338.                     putchar( cnts[j][k] ? cnts[j][k]+'0' : '0' );
  339.                 }
  340.                 if( j==0 ) {
  341.                     printf( "\n  Primary Guess: " );
  342.                 } else {
  343.                     printf( "\n     Alternates: " );
  344.                 }
  345.                 csum = 0;
  346.                 for( k=0; k<len; k++ ) {
  347.                     putchar( cnts[j][k] ? fmt[j][k] : ' ' );
  348.                     if( cnts[j][k] ) {
  349.                         csum = ( (csum >> 1) | ( csum << 15) ) ^ ( fmt[j][k]<<8 );
  350.                     }
  351.                 }
  352.         if( j==0 ) {
  353.                     if (missing) {
  354.                         printf("  (Incomplete!)");
  355.                     } else {
  356.                         if( csum == csum1 ) {
  357.                             printf("  Checksum good!");
  358.                         } else {
  359.                             printf("  Checksum bad!");
  360.                         }
  361.                     }
  362.                 }
  363.  
  364.                 if( do_dec ) {
  365.                     printf( "\n                 " );
  366.                     for(k=0; k<len; k++) {
  367.                         printf("%d ", cnts[j][k] ? fmt[j][k] : 0);
  368.                     }
  369.                 }
  370.  
  371.         /* if only one missing character, extrapolate */
  372.                 if( missing == 1 && j==0 ) {
  373.                     for( i=0; i<128; i++ ) {
  374.                         csum = 0;
  375.                         fmt[0][mi] = i;
  376.                         for( k=0; k<len; k++ ) {
  377.                             csum = ( (csum >> 1) | ( csum << 15) ) ^ ( fmt[0][k]<<8 );
  378.                         }
  379.                         if( csum == csum1 && ( i<'a' || i>='z' )) {
  380.                             printf( "\n   Extrapolated: " );
  381.                             for( k=0; k<len; k++ ) putchar( fmt[j][k] );
  382.                             printf( "   -- Good Checksum");
  383.                             if( do_dec ) {
  384.                                 printf( "\n                 " );
  385.                                 for(k=0; k<len; k++) printf("%d ", fmt[j][k]);
  386.                             }
  387.                         }
  388.                     }
  389.                 }
  390.  
  391.                 printf( "\n\n" );
  392.             }
  393.         } else {
  394.  
  395.             for( k=0; k<len; k++ ) {
  396.                 idx[k]=0;
  397.                 cur[k]=fmt[0][k];
  398.             }
  399.  
  400.             if( missing == 1 ) {
  401.                 cur[mi] = ' ';
  402.                 printf( "  " );
  403.                 for( k=0; k<len; k++ ) putchar( cur[k] );
  404.                 printf( "\n  ");
  405.                 for( k=0; k<len; k++ )
  406.                     putchar( k == mi ? '^' : ' ');
  407.                 printf( "\n The missing character will be extrapolated from the checksum\n\n");
  408.             } else {
  409.                 printf( " Only possibilities with good checksums will be listed.\n\n");
  410.             }
  411.  
  412.             do {
  413.                 if( missing == 0 ) {
  414.  
  415.           /* none missing - generate,  check checksum */
  416.                     csum = 0;
  417.                     for( k=0; k<len; k++ ) {
  418.                         csum = ( (csum >> 1) | ( csum << 15) ) ^ ( cur[k]<<8 );
  419.                     }
  420.                     if( csum == csum1 ) {
  421.                         printf( "  " );
  422.                         for( k=0; k<len; k++ ) {
  423.                             putchar( cur[k] );
  424.                         }
  425.                         printf( "   -- Good Checksum\n");
  426.                         if( do_dec ) {
  427.                             printf( "   Dec: " );
  428.                             for( k=0; k<len; k++ ) {
  429.                                 printf( "%d ", cur[k] );
  430.                             }
  431.                             printf( "\n");
  432.                         }
  433.                     }
  434.                 } else {
  435.  
  436.           /* checksum missing - generate */
  437.                     tot = 0;
  438.                     for( i=0; i<128; i++ ) {
  439.                         csum = 0;
  440.                         cur[mi] = i;
  441.                         for( k=0; k<len; k++ ) {
  442.                             csum = ( (csum >> 1) | ( csum << 15) ) ^ ( cur[k]<<8 );
  443.                         }
  444.                         if( csum == csum1 && ( i<'a' || i>='z' )) {
  445.                             tot++;
  446.                             printf( "  " );
  447.                             for( k=0; k<len; k++ ) putchar( cur[k] );
  448.                             printf( "   -- Good Checksum\n");
  449.                             if( do_dec) {
  450.                                 printf("  ");
  451.                                 for( k=0; k<len; k++ ) printf("%d ",cur[k]);
  452.                                 printf("\n");
  453.                             }
  454.                         }
  455.                     }
  456.                     if( !tot ) {
  457.                         printf("  No valid passwords found\n" );
  458.                     }
  459.                 }
  460.  
  461.         /* next combination */
  462.                 k=len-1;
  463.                 while( k>=0 ) {
  464.                     if( cnts[idx[k]+1][k]==0 || cur[k]== N-1 ) {
  465.             idx[k]=0;
  466.                         k--;
  467.                     } else {
  468.                         idx[k]++;
  469.                         break;
  470.                     }
  471.                 }
  472.  
  473.             } while( k>=0 );
  474.         } /* table or checksum */
  475.     }
  476. }
  477.